#include "str.h"

#include "table.h"

void read_string(Table *table, RID rid, StringRecord *record) {
    table_read(table, rid, record->chunk.data);
    record->idx = 0;
}

int has_next_char(StringRecord *record) {
    return !((record->idx == get_str_chunk_size(record)) && 
             (get_rid_block_addr(get_str_chunk_rid(record)) == -1));
}

char next_char(Table *table, StringRecord *record) {
    if(!has_next_char(record))
        return '\0';
    if(record->idx == get_str_chunk_size(record))
        read_string(table, get_str_chunk_rid(record), record);
    return get_str_chunk_data_ptr(record)[record->idx++];
}

int compare_string_record(Table *table, const StringRecord *a, const StringRecord *b) {
    StringRecord tmp_a = *a, tmp_b = *b;
    while(1){
        char cha = next_char(table, &tmp_a);
        char chb = next_char(table, &tmp_b);
        if(cha < chb || (cha == '\0' && chb != '\0'))
            return -1;
        else if(cha > chb || (cha != '\0' && chb == '\0'))
            return 1;
        else if(cha == '\0' && chb == '\0')
            return 0;
        else
            continue;
    }
}

RID write_string(Table *table, const char *data, off_t size) {
    short i = 0, j = 0;
    short chunck_num = (size == 0) ? 0 : (size - 1) / STR_CHUNK_MAX_LEN;
    short last_size = size - chunck_num * STR_CHUNK_MAX_LEN;
    StringChunk chunk;
    RID rid;
    get_rid_block_addr(rid) = -1;
    get_rid_idx(rid) = -1;
    for(i = chunck_num; i >= 0; i--){
        get_str_chunk_rid(&chunk) = rid;
        get_str_chunk_size(&chunk) = last_size;
        for(j = 0; j < last_size; j++)
            get_str_chunk_data_ptr(&chunk)[j] = data[j + i * STR_CHUNK_MAX_LEN];
        rid = table_insert(table, chunk.data, calc_str_chunk_size(last_size));
        last_size = STR_CHUNK_MAX_LEN;
    }
    return rid;
}

void delete_string(Table *table, RID rid) {
    StringChunk chunk;
    RID rid_now, rid_next;
    table_read(table, rid, chunk.data); // read first chunk
    rid_now = rid;
    rid_next = get_str_chunk_rid(&chunk);
    while(get_rid_block_addr(rid_next) != -1){ // has next chunk
        table_delete(table, rid_now);
        table_read(table, rid_next, chunk.data);
        rid_now = rid_next;
        rid_next = get_str_chunk_rid(&chunk);
    }
    table_delete(table, rid_now);
}

// /* void print_string(Table *table, const StringRecord *record) {
//     StringRecord rec = *record;
//     printf("\"");
//     while (has_next_char(&rec)) {
//         printf("%c", next_char(table, &rec));
//     }
//     printf("\"");
// } */

size_t load_string(Table *table, const StringRecord *record, char *dest, size_t max_size) {
    StringRecord tmp_record = *record;
    size_t cnt = 0;
    while(has_next_char(&tmp_record) && cnt < max_size)
        dest[cnt++] = next_char(table, &tmp_record);
    return cnt;
}

// /* void chunk_printer(ItemPtr item, short item_size) {
//     if (item == NULL) {
//         printf("NULL");
//         return;
//     }
//     StringChunk *chunk = (StringChunk*)item;
//     short size = get_str_chunk_size(chunk), i;
//     printf("StringChunk(");
//     print_rid(get_str_chunk_rid(chunk));
//     printf(", %d, \"", size);
//     for (i = 0; i < size; i++) {
//         printf("%c", get_str_chunk_data_ptr(chunk)[i]);
//     }
//     printf("\")");
// } */
